package com.cooper.scraper;

import java.util.ArrayList;
import java.util.List;

import android.util.SparseArray;

import com.cooper.android.comm.Resource;

public abstract class ResourceCollector<T extends Resource> {

	private ResourceScraper<T> scraper;

	private String scraperId;
	private SparseArray<ScraperBrowseParam> scraperParams = new SparseArray<ScraperBrowseParam>();
	private List<T> medias;

	protected int pageCount;
	protected int pageNumber;

	// private String keyPrefix;

	private List<String> removeIds = new ArrayList<String>(0);

	public ResourceCollector(String scraperId) {
		super();
		this.scraperId = scraperId;
		resetPageCount();

	}

	public ResourceCollector(String scraperId, List<String> removeIds) {
		this(scraperId);
		this.removeIds = removeIds;
	}

	public List<String> getRemoveIds() {
		return removeIds;
	}

	public void setRemoveIds(List<String> removeIds) {
		this.removeIds = removeIds;
	}

	public String getScraperId() {
		return this.scraperId;
	}

	public boolean ready() {
		return scraper != null;
	}

	public void putParams(List<ScraperBrowseParam> scraperBrowseParams) {
		for (ScraperBrowseParam scraperBrowseParam : scraperBrowseParams) {
			putParams(scraperBrowseParam);
		}
	}
	
	public void putParams(ScraperBrowseParam scraperBrowseParam){
		if (scraperBrowseParam.getPosition() == 1
				|| scraperBrowseParam.getType() == ScraperBrowseParam.PAGE_NUMBER_PARAM) {
			throw new IllegalArgumentException(
					"position 1: type PAGE_NUMBER_PARAM cant't put");
		}
		scraperParams.put(scraperBrowseParam.getPosition(),
				scraperBrowseParam);
	}

	// private ScraperBrowseParam get

	// TODO extract OnlineMediaScrapeRunnr base class and remove public
	public void setScraper(ResourceScraper<T> scraper,
			List<ScraperBrowseParam> browseParams) {
		this.scraper = scraper;
		if (scraper != null) {
			this.scraperId = scraper.getId();
			if (browseParams != null) {
				for (ScraperBrowseParam param : browseParams) {
					if (scraperParams.indexOfKey(param.getPosition()) < 0) {
						scraperParams.put(param.getPosition(), param);
					}
				}
			}
		}
		reset();
	}

	public boolean BOF() {
		return medias == null;
	}

	public abstract boolean EOF();

	public abstract boolean hasNextPage();

	public abstract void nextPage();

	public int getPageCount() {
		return pageCount;
	}

	public abstract int getCurrPageNumber();

	protected abstract void resetPageCount();

	private void setMedias(List<T> medias) {
		this.medias = new ArrayList<T>();
		for (T media : medias) {
			if (!removeIds.contains(media.getId())) {
				this.medias.add(media);
			}
		}
	}

	public final List<T> getMedias() {
		return medias;
	}

	private void resetMedias() {
		medias = null;
	}

	public final void reset() {
		resetMedias();
		resetPageCount();
	}

	public final boolean noResult() {
		if (medias == null) {
			throw new IllegalStateException("not call download yet");
		} else {
			return medias.isEmpty() && !hasNextPage();
		}
	}

	private void setPageCount(int pageCount) {
		if (pageNumber <= pageCount || this.pageCount == -1) {
			this.pageCount = pageCount;
		}
	}

	public final String generateKey() {
		String result;
		if (ready()) {
			result = "BROWSE_LIST_KEY_" + scraperId + "_";
			for (int i = 0; i < scraperParams.size(); i++) {
				ScraperBrowseParam param = scraperParams.valueAt(i);
				if (param.getType() != ScraperBrowseParam.PAGE_NUMBER_PARAM) {
					result += "_" + param.getKey();
				}
			}
			result += "_P_" + pageNumber;
		} else {
			result = "GET_BROWSE_SCRAPER_KEY_" + scraperId;
		}
		return result;
	}

	private List<ScraperBrowseParam> getBrowseUrlParams() {
		scraperParams.put(1, new ScraperBrowseParam(pageNumber));
		List<ScraperBrowseParam> result = new ArrayList<ScraperBrowseParam>(
				scraperParams.size());
		for (int i = 0; i < scraperParams.size(); i++) {
			result.add(scraperParams.valueAt(i));
		}
		return result;
	}

	public final ResultUrl scraperListUrl() throws ScraperException,
			DownloadException {
		return scraper.createBrowseUrl(getBrowseUrlParams());
	}

	public final void scraperResult(String page, String referer)
			throws ScraperException, DownloadException {
		setMedias(scraper.extractBrowseResource(page, referer));
	}

	public final void scraperResult(String page, String referer,
			String redirectUrl) throws ScraperException, DownloadException {
		setMedias(scraper.extractBrowseResource(page, referer, redirectUrl));
	}

	public ResultUrl scraperPageCountUrl() throws DownloadException,
			ScraperException {
		return scraper.createBrowseUrl(getBrowseUrlParams());
	}

	public void scraperPageCount(String page) throws DownloadException,
			ScraperException {
		setPageCount(scraper.getBrowsePageCount(page));
	}

	public void scraperPageCount(String page, String redirectUrl)
			throws DownloadException, ScraperException {
		setPageCount(scraper.getBrowsePageCount(page, redirectUrl));
	}

	public final boolean subscribed(String key) {
		return key.equals(generateKey());
	}

}
